/*
 * Copyright (C) 2010 Seapeak.Xu
 *
 * fostmq may be copied only under the terms of the GNU General
 * Public License V3, which may be found in the fostmq source kit.
 *
 * Created on: 2010-8-4
 * Author: Seapeak.Xu
 */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stddef.h>
#include <errno.h>
#include <unistd.h>
#include <sys/signal.h>
#include <string.h>

#include "fost_thread.h"
#include "fost_typedef.h"
#include "fost_logger.h"

int set_thread_stacksize(pthread_attr_t *attr, const size_t stack_size)
{
	int result = 0;
	if (NULL == attr)
	{
		return -1;
	}
	if (0 >= stack_size)
	{
		return 0 == errno ? EINVAL : errno;
	}
	size_t ostack_size = 0;
	pthread_attr_getstacksize(attr, &ostack_size);
	if (ostack_size == stack_size * 1024)
	{
		return result;
	}
	if (0 != (result = pthread_attr_setstacksize(attr, stack_size * 1024 * 1024)))
	{
		return result;
	}
	return result;
}

int kill_working_thread(pthread_t tid)
{
	
	return pthread_kill(tid, SIGINT);
}

int create_working_thread(void *(*callback)(void *),void *arg)
{
	pthread_t thread;
	if(0 > pthread_create(&thread,NULL,callback,arg))
	{
		log_error("File:%s,Line:%d,Function:%s.create working thread is error.errno:%d,info:%s.",
				__FILE__,__LINE__,__FUNCTION__,errno,strerror(errno));
		return -1;
	}
	return 0;
}
int detach_thread(pthread_attr_t *attr, bool isdetach)
{
	if (NULL == attr)
	{
		return -1;
	}
	int odetach;
	int result = 0;
	if (0 != (result = pthread_attr_getdetachstate(attr, &odetach)))
	{
		return result;
	}

	if (isdetach)
	{
		if (PTHREAD_CREATE_DETACHED == odetach)
		{
			return result;
		}
		else
		{
			return pthread_attr_setdetachstate(attr, PTHREAD_CREATE_DETACHED);
		}
	}
	else
	{
		if (PTHREAD_CREATE_JOINABLE == odetach)
		{
			return result;
		}
		else
		{
			return pthread_attr_setdetachstate(attr, PTHREAD_CREATE_JOINABLE);
		}
	}
	return result;
}

int thread_mutexlocker_init(pthread_mutex_t *locker)
{
	int result = 0;
	pthread_mutexattr_t attr;
	if (0 != (result = pthread_mutexattr_init(&attr)))
	{
		return result;
	}

	do
	{
		int pshared;
		if (0 != (result = pthread_mutexattr_getpshared(&attr, &pshared)))
		{
			break;
		}

		if (PTHREAD_PROCESS_PRIVATE != pshared)
		{
			if (0 != (result = pthread_mutexattr_setpshared(&attr,
					PTHREAD_PROCESS_PRIVATE)))
			{
				break;
			}
		}

#ifdef __USE_UNIX98

		if(0 != (result = pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK)))
		{
			break;
		}
#else
		if(0 != (result = pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_ERRORCHECK_NP)))
		{
			break;
		}
#endif

		if (0 != (result = pthread_mutex_init(locker, &attr)))
		{
			break;
		}
	} while (false);
	
	result = pthread_mutexattr_destroy(&attr);
	return result;
}

int thread_condlocker_init(pthread_cond_t *locker)
{
	int result = 0;
	pthread_condattr_t attr;
	if (0 != (result = pthread_condattr_init(&attr)))
	{
		return result;
	}

	do
	{
		int pshared;
		if (0 != (result = pthread_condattr_getpshared(&attr, &pshared)))
		{
			break;
		}

		if (PTHREAD_PROCESS_PRIVATE != pshared)
		{
			if (0 != (result = pthread_condattr_setpshared(&attr,
					PTHREAD_PROCESS_PRIVATE)))
			{
				break;
			}
		}

		if (0 != (result = pthread_cond_init(locker, &attr)))
		{
			break;
		}
	} while (false);
	result = pthread_condattr_destroy(&attr);
	return result;
}

// i donot understand why i define the two function.
// if you want to konw,please ask god.
